<?php defined('BASEPATH') OR exit('No direct script access allowed');


//重载CI_Model核心类库是为了自动加载: Base_model主库model基类 和 Base_copy从库model基类
//方便其它模型类扩展


/**
 * My_Model 类 扩展CI_Model核心类
 */
class My_Model extends CI_Model {
	public function __construct()
	{
		parent::__construct();

		//$this->db->trans_strict(FALSE); //关闭事务严格模式(严格模式下, 只要一组事务出错, 其它组事务也会回滚)
	}
}



/**
 * Base_model 主库model基类
 */
class Base_model extends CI_Model {

    /**
     * 记录id.
     * @var int
     */
    public $id;


    /**
     * 当前模型数据库表名称.
     * @var string
     */
    public $_table_name;


    /**
     * 查询包含的字段
     * 
     * @var sting or array
     */
    public $_selected_fields;


    /**
     * 是否为总数查询.
     * 
     * @var boolean
     */
    public $_is_search_counter;


    /**
     * 分页查询 - 起始页号.
     * @var int
     */
    public $_page_index;


    /**
     * 分页查询 - 每页数量.
     * @var int
     */
    public $_page_count;


    /**
     * 查询排序方式
     * @var string
     */
    public $_order_by;


    /**
     * 更新记录 -- 字段条件数组
     * @var array
     */
    public $_update_where;


    /**
     * 删除记录 -- 字段条件数组
     * @var array
     */
    public $_delete_where;


    /**
     * GROUP BY 语句.
     * @var string
     */
    public $_group_by;


    /**
     * 查询结果数组
     * @var array
     */
    public $_search_results;


    /**
     * 查询结果数量
     * @var int
     */
    public $_search_num_rows;


    /**
     * 插入字段数组
     * @var array
     */
    protected $_insert_fields;


    /**
     * 更新字段数组
     * @var array
     */
    protected $_update_fields;


    /**
     * 构造函数
     */
    public function __construct()
    {
        parent::__construct();

		//$this->db->trans_strict(FALSE); //关闭事务严格模式(严格模式下, 只要一组事务出错, 其它组事务也会回滚)

		//初始化成员变量        
        $this->_search_num_rows = 0;
        $this->_search_results = array();
        $this->_insert_fields = array();
        $this->_update_fields = array();
        $this->_update_where = array();
        $this->_delete_where = array();

		//查看表前缀
        $reg = "/^" . $this->db->dbprefix . "/is";

		//如果没有加表前缀, 则加表前缀
        if(!preg_match($reg, $this->_table_name))
		{
            $this->_table_name = $this->db->dbprefix . $this->_table_name;
		}
	}

    
    /**
     * 加载数据对象.
     *
     * @param string $id
     * @return boolean
     */
    public function retrieve($id)
	{
        if(empty($id))
		{
            return false;
        }

        $sql = "SELECT * FROM {$this->_table_name} WHERE id = ? LIMIT 1";

        $result = $this->db->query($sql, array($id));

		$re = false; //初始化返回结果

        if($result->num_rows() > 0)
		{
            $this->result_load($result->row());

            if(!$this->is_empty())
			{
				$re = true;
            }
        }

		$result->free_result();

		return $re;
	}


    /**
     * 默认搜索返回空数组.
     *
     * @return array
     */
    public function search()
    {
        return true;
    }

	
    /**
     * 插入数据前初始化字段
     *
     * @return boolean
     */
    private function prepare_insert_fields()
    {
        $this->_insert_fields = array();
   
        foreach(get_object_vars($this) as $key => $value)
        {
            if($key{0} != '_' && $key != 'id' && !is_object($this->$key) && !is_array($this->$key))
            {
				$this->_insert_fields[$key] = $value;
            }
        }
        
        if(empty($this->_insert_fields))
        {
            return false; //不能插入空数据
        }
        else
        {
            return true;
        }
    }

    
    /**
     * 插入数据前验证数据.
     */
    protected function prepare_insert()
    {
       return true; 
    }
    

    /**
     * 插入数据到database.
     *
     * @return boolean
     */
    public function insert()
    {
        if(!$this->prepare_insert())
        {
            return false;
        }
       
        if(!$this->prepare_insert_fields())
        {
            return false;
        }
       
        $fields = "";
        $values = "";

        foreach($this->_insert_fields as $k => $v)
        {
            $fields .= "`{$k}`,";
            $values .= $this->db->escape($v) . ",";
        }
        
        $fields = trim($fields, ",");
        $values = trim($values, ",");
        
        $sql = "INSERT INTO {$this->_table_name} ({$fields}) VALUES ({$values})";
    
        $this->db->query($sql);        

        if($this->db->affected_rows() > 0)
        {       
            $this->id = $this->db->insert_id(); //插入成功后仅设置当前模型的id
            
            return true;
        }
        else
        {
            $this->id = 0;

            return false;
        }
    }


    /**
     * update数据前预处理字段, 值无变化的字段不更新
     */
    protected function prepare_update_fields()
    {

		$this->_update_fields = array();
		
		foreach(get_object_vars($this) as $key => $value)
		{
			if($key{0} != '_' && $key != 'id' && $value !== null && !is_object($this->$key) && !is_array($this->$key))
			{
				$this->_update_fields[$key] = $value;
			}
		}

		if(empty($this->_update_fields))
		{
			return false;
		}

		return true;
    }


    /**
     * 更新数据前验证数据.
     */
    protected function prepare_update()
    {
        return true;
    }

   
    /**
     * update数据.
     *
     * @return boolean
     */
    public function update()
    {
        if(!$this->prepare_update())
        {
            return false;
        }

		if(!$this->prepare_update_fields())
        {
            return false;
        }
        
      
        $sql_str = "";
                
        foreach($this->_update_fields as $k => $v)
        {
            $sql_str .= "`{$k}`=" . $this->db->escape($v) . ",";           
        }

        $sql_str = trim($sql_str, ",");
                        
        $sql = "UPDATE {$this->_table_name} SET {$sql_str} WHERE ";

		if(!$this->is_empty())
		{
            $sql .= " id = '{$this->id}'";

			$this->db->query($sql);
		}
		else
		{
			//处理条件
			$statement = "";
			$where = array();

			foreach($this->_update_where AS $key => $val)
			{
				$statement .= " AND {$key} = ? ";
				$where[] = $val;
			}

			$sql .= substr($statement, 4);

			$this->db->query($sql, $where);
		}

            
        if($this->db->affected_rows() > 0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }


    /**
     * 删除数据前验证数据.
     * @return true if successful, false if not.
     */
    protected function prepare_delete()
    {
        return true;
    }
    

    /**
     * 删除数据.
     *
     * @return boolean if successful, false if not.
     */
    public function delete()
    {
        if(!$this->prepare_delete())
        {
            return false;
        }

        $sql = "DELETE FROM {$this->_table_name} WHERE "; 

		if(!$this->is_empty())
		{
            $sql .= " id = '{$this->id}'";

			$this->db->query($sql);
		}
		else
		{
			//处理条件
			$statement = "";
			$where = array();

			foreach($this->_delete_where AS $key => $val)
			{
				$statement .= " AND {$key} = ? ";
				$where[] = $val;
			}

			$sql .= substr($statement, 4);

			$this->db->query($sql, $where);
		}

        if ($this->db->affected_rows() > 0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    

	/**
     * 根据id批量删除数据.
     *
     * @param string OR array $ids
     * @return boolean if successful, false if not.
     */
    public function delete_by_ids($ids = '')
    {
        if (empty($ids))
		{
            return false;
		}

		if(is_string($ids))
		{
			$ids = explode(',', trim(trim($ids), ','));
		}

        $sql = "DELETE FROM {$this->_table_name} WHERE id IN ?"; 
		$this->db->query($sql, array($ids));

        if ($this->db->affected_rows() > 0)
        {
            return true;
        }
        else
        {
            return false;
        }
	}


    /**
     * 加载数据到当前对象.
     *
     * @param Mixed $obj，object或array
     * @return boolean true if success, false if faild.
     */
    public function result_load($obj)
    {
        if (empty($obj))
		{
            return false;
		}

        if (is_array($obj))
        {
            foreach($obj as $key => $value)
            { 
				if (property_exists($this, $key) && !is_object($this->$key) && !is_array($this->$key))
				{
					$this->$key = $value;
				}
            }
        }
        else
        {            
            foreach(get_object_vars($obj) as $key => $value)
            {           
                if (property_exists($this, $key) && !is_object($this->$key) && !is_array($this->$key))
                {
					$this->$key = $value;
                }
            }
        }
        
        return true;
    }


    /**
     * 检查对象是否为空对象.
     *
     * @return boolean
     */
    public function is_empty()
    {
        return empty($this->id);
    }

      
    /**
     * 检查当前查询是否分页, 并转换分页值.
     *
     * @return boolean True if paging is enabled, false if not.
     */
    public function is_paging()
    {
		$this->_page_index = intval($this->_page_index);
		$this->_page_count = intval($this->_page_count);

		if(empty($this->_page_count))
		{
			$this->_page_count = 10;
		}

        return (!empty($this->_page_index));
    }
    

    /**
     * 清空对象(属性). 不能清空模型数据库表名称
     *
     * @return boolean true if success,false if faild.
     */
    public function empty_self()
    {
        foreach(get_object_vars($this) as $key => $value)
        {
            if($key != '_table_name')
            {
                $this->$key = null;
            }
        }

        $this->_search_num_rows = 0;
        $this->_search_results = array();
        $this->_insert_fields = array();
        $this->_update_fields = array();
        $this->_update_where = array();
        $this->_delete_where = array();
        
        return true;
    }
    
}



/**
 * Base_copy 从库model基类
 */
class Base_copy extends CI_Model {
    
    /**
     * 记录id.
     * @var int
     */
    public $id;


    /**
     * 当前模型数据库表名称.
     * @var string
     */
    public $_table_name;


    /**
     * 查询包含的字段
     * 
     * @var sting or array
     */
    public $_selected_fields;


    /**
     * 是否为总数查询.
     * 
     * @var boolean
     */
    public $_is_search_counter;


    /**
     * 分页查询 - 起始页号.
     * @var int
     */
    public $_page_index;


    /**
     * 分页查询 - 每页数量.
     * @var int
     */
    public $_page_count;


    /**
     * 查询排序方式
     * @var string
     */
    public $_order_by;


    /**
     * GROUP BY 语句.
     * @var string
     */
    public $_group_by;


    /**
     * 查询结果数组
     * @var array
     */
    public $_search_results;


    /**
     * 查询结果数量
     * @var int
     */
    public $_search_num_rows;


    /**
     * 数据库链接资源
     * @var object 
     */
    protected $db;


    /**
     * 构造函数
     */
    public function __construct()
    {
        parent::__construct();

		//初始化成员变量        
        $this->_search_num_rows = 0;
        $this->_search_results = array();

		$this->connect_db_copy();

		//查看表前缀
        $reg = "/^" . $this->db->dbprefix . "/is";

		//如果没有加表前缀, 则加表前缀
        if(!preg_match($reg, $this->_table_name))
		{
            $this->_table_name = $this->db->dbprefix . $this->_table_name;
		}

    }

    
    /**
     * 连接copy数据库
     */
    protected function connect_db_copy()
    {
        $this->db = $this->load->database("db_copy", TRUE);
        
        if (empty($this->db) || ( ! is_object($this->db)))
        {
            $this->db = null;
        }
        
        return true;
    }

    
    /**
     * 加载数据对象.
     *
     * @param string $id
     * @return boolean
     */
    public function retrieve($id)
	{
        if(empty($id))
		{
            return false;
        }

        $sql = "SELECT * FROM {$this->_table_name} WHERE id = ? LIMIT 1";

        $result = $this->db->query($sql, array($id));

		$re = false; //初始化返回结果

        if($result->num_rows() > 0)
		{
            $this->result_load($result->row());

            if(!$this->is_empty())
			{
				$re = true;
            }
        }

		$result->free_result();

		return $re;
	}


    /**
     * 默认搜索返回空数组.
     *
     * @return array
     */
    public function search()
    {
        return true;
    }

    
    /**
     * 加载数据到当前对象.
     *
     * @param Mixed $obj，object或array
     * @return boolean true if success, false if faild.
     */
    public function result_load($obj)
    {
        if (empty($obj))
		{
            return false;
		}

        if (is_array($obj))
        {
            foreach($obj as $key => $value)
            { 
				if (property_exists($this, $key) && !is_object($this->$key) && !is_array($this->$key))
				{
					$this->$key = $value;
				}
            }
        }
        else
        {            
            foreach(get_object_vars($obj) as $key => $value)
            {           
                if (property_exists($this, $key) && !is_object($this->$key) && !is_array($this->$key))
                {
					$this->$key = $value;
                }
            }
        }
        
        return true;
    }


    /**
     * 检查对象是否为空对象.
     *
     * @return boolean
     */
    public function is_empty()
    {
        return empty($this->id);
    }

      
    /**
     * 检查当前查询是否分页, 并转换分页值.
     *
     * @return boolean True if paging is enabled, false if not.
     */
    public function is_paging()
    {
		$this->_page_index = intval($this->_page_index);
		$this->_page_count = intval($this->_page_count);

		if(empty($this->_page_count))
		{
			$this->_page_count = 10;
		}

        return (!empty($this->_page_index));
    }
    

    /**
     * 清空对象(属性). 不能清空模型数据库表名称及$db对象
     *
     * @return boolean true if success,false if faild.
     */
    public function empty_self()
    {
        foreach(get_object_vars($this) as $key => $value)
        {
            if($key != '_table_name' OR $key != 'db')
            {
                $this->$key = null;
            }
        }

        $this->_search_num_rows = 0;
        $this->_search_results = array();
        
        return true;
    }
    
}